﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Drawing;

namespace LowLevelGraphics.ColorSpaces
{
    /// <summary>
    /// Normalized RGB Channel
    /// </summary>
    public enum NormalizedRGBChannel
    {
        /// <summary>
        /// 
        /// </summary>
        R = 0,
        /// <summary>
        /// 
        /// </summary>
        G = 1,
        /// <summary>
        /// 
        /// </summary>
        B = 2
    }

    /// <summary>
    /// Unless other color spaces this does not allow a
    /// a-&gt;b b-&gt;a transformation, because a will be changed into b by omitting some informations
    /// so the transformation is not reversible
    /// And also we need no explicite normalize function in this case because this color space IS
    /// already normalized
    /// </summary>
    [DebuggerDisplay("R: {m_R}, G: {m_G}, C: {m_B}")]
    public class NormalizedRGB : AbstractColorSpace
    {
        protected double m_dR = 0.0f;
        protected double m_dG = 0.0f;
        protected double m_dB = 0.0f;

        /// <summary>
        /// Construct a new HCL
        /// </summary>
        /// <param name="_color"></param>
        public NormalizedRGB(Color _color)
            : base(_color)
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="NormalizedRGB"/> class.
        /// </summary>
        /// <param name="_dR">The _d R.</param>
        /// <param name="_dG">The _d G.</param>
        /// <param name="_dB">The _d B.</param>
        public NormalizedRGB(double _dR, double _dG, double _dB)
        {
            m_dR = _dR;
            m_dG = _dG;
            m_dB = _dB;
        }

        /// <summary>
        /// used by clone to create a deep copy
        /// </summary>
        /// <param name="_normalizedRGB">The _normalized RGB.</param>
        internal NormalizedRGB(NormalizedRGB _normalizedRGB)
        {
            this.m_dR = _normalizedRGB.m_dR;
            this.m_dG = _normalizedRGB.m_dG;
            this.m_dB = _normalizedRGB.m_dB;
        }

        /// <summary>
        /// Convert
        /// </summary>
        protected override void CalcValues()
        {
            int nR = m_Color.R;
            int nG = m_Color.G;
            int nB = m_Color.B;
            //Add 1 if color is black otherwise we would get a "divided by zero exception" 
            int nColorChannelSum = nR + nG + nB + 1;
            m_dR = (double)nR / nColorChannelSum * 256;
            m_dG = (double)nG / nColorChannelSum * 256;
            m_dB = (double)nB / nColorChannelSum * 256;
        }

        /// <summary>
        /// Gets or sets Y
        /// </summary>
        public double R
        {
            get { return m_dR; }
            set { m_dR = value; }
        }

        /// <summary>
        /// Gets or sets the G.
        /// </summary>
        /// <value>The G.</value>
        public double G
        {
            get { return m_dG; }
            set { m_dG = value; }
        }

        /// <summary>
        /// Override this to implement retransformation of concrete color space
        /// back to rgb
        /// </summary>
        /// <returns></returns>
        public override Color ToColor()
        {
            return Color.FromArgb((int)m_dR+ (int)m_dG + (int)m_dB);
        }

        /// <summary>
        /// Gets the values.
        /// </summary>
        /// <returns></returns>
        public override object[] GetValues()
        {
            return new object[] { m_dR, m_dG, m_dB };
        }

        /// <summary>
        /// Sets the values.
        /// </summary>
        /// <param name="_aObject">The _a object.</param>
        public override void SetValues(object[] _aObject)
        {
            this.m_dR = (double)_aObject[0];
            this.m_dG = (double)_aObject[1];
            this.m_dB = (double)_aObject[2];
        }

        /// <summary>
        /// enables caller to cast a caller into this color space
        /// </summary>
        /// <param name="_color"></param>
        /// <returns></returns>
        public static explicit operator NormalizedRGB(Color _color)
        {
            return new NormalizedRGB(_color);
        }
    }
}
